import numpy as np

def _AND(x1, x2):
    return np.multiply(x1, x2)

def _OR(x1, x2):
    return np.maximum(x1, x2)

def _NOT(x1):
    return 1-x1

def _Recall_loss(y, y_pred, w):
    # 根据 y_pred 对样本排序，降序排列
    sorted_indices = np.argsort(y_pred)[::-1]
    
    #topk的k选择多少
    top_k = [0.4]
    positive_nodes_ratio = 0
    negative_nodes_ratio = 0
    # cnt = 0
    # true_label_num = 10
    # 计算前topk节点的数量
    for k in top_k:
        top_k_percent = int(k * len(y))

    # 获取前k节点的真实标签
        top_k_percent_labels = y[sorted_indices][:top_k_percent]

    # 计算前50%节点中真实节点的比例
    # for index in sorted_indices:
    #     if index <= true_label_num:
    #         cnt+=1
    # real_nodes_ratio = cnt / true_label_num
        positive_nodes_ratio += np.sum(top_k_percent_labels) / np.sum(y)
        negative_nodes_ratio += (int(k * len(y)) - np.sum(top_k_percent_labels)) / (len(y) - np.sum(y))
    avg_nodes_ratio = (positive_nodes_ratio - negative_nodes_ratio) / len(top_k)
#  + np.average(((y_pred - y) ** 2), weights=w)
    return 1 - avg_nodes_ratio  # 最小化 loss，等价于最大化真实节点比例

def _Recall_lut_loss(y, y_pred, w):
    # 根据 y_pred 对样本排序，降序排列
    positive_indexes = np.where(y==1)[0]
    predict_positive_indexes = np.where(y_pred==1)[0]
    intersection = np.intersect1d(positive_indexes, predict_positive_indexes)
    cnt = len(intersection)
    recall = cnt/len(positive_indexes)
    positive_ratio = len(predict_positive_indexes)/len(y_pred)
    return 1 - recall +  0.3 * positive_ratio

def GNN_Recall_loss(y, y_pred, w):      # y按照先正节点后负节点排序
    # 根据 y_pred 对样本排序，升序排列
    sorted_indices = np.argsort(y_pred)

    # 正节点的数量
    true_label_num = 7738
    total_num = len(y)
    #topk取值
    k = 0.4
    
    #计数cnt
    cnt=0
    
    # 计算前topk节点的数量
    top_k_percent = int(k * total_num)

    # 获取前k节点的indexes
    top_k_percent_labels = sorted_indices[total_num-top_k_percent:]

    # 计算前topk节点中真实节点的比例
    for index in top_k_percent_labels:
        if index <= true_label_num:
            cnt+=1
    real_nodes_ratio = cnt / true_label_num
    return 1 - real_nodes_ratio # 最小化 loss，等价于最大化真实节点比例